//
// Created by Crestimes on 2024/11/18.
//

#ifndef FAMANAGER_H
#define FAMANAGER_H

#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

#include "Fas.h"
using namespace std;


class FABuilder {
public:
    FABuilder(const map<string, string>& reMap, const set<string>& reOfTokenType, const set<string>& reForAuxiliary);
    map<string, pair<map<size_t, map<string, size_t>>, set<size_t>>> DFAsAndEndsOfTokenType; // 所有正则名带_前缀的DFA图和对应的终点集
    map<string, pair<map<size_t, map<string, size_t>>, set<size_t>>> DFAsAndEndsOfAuxiliary;
    // ^^^所有会出现在reOfTokenType的正则值中的正则名的DFA图和对应的终点集

private:
    void buildDFAs();

    // 通用成员变量
    map<string, string> reMap; // 正则名到正则值的映射
    set<string> reOfTokenType; // 所有token类型对应的正则名
    set<string> reForAuxiliary; // 会出现在reOfTokenType的正则值中的正则名
    string reNameNow; // 当前处理的正则表达式名
    string reValueNow; // 当前处理的正则表达式值
    set<string> symbols; // 所有符号
    set<size_t> ends; // 终点下标集合
    size_t start = 0; // 起点下标

    // 工具函数
    static string setToStr(const set<size_t>& epsilonSet);
    static set<size_t> strToSet(string setString);
    void clear();

    // 初始化操作
    void initBeforeGenerate(const string& reName);

    // 生成NFA
    void generateNFA();
    void initSuffixRe();
    void calcSuffixRe();
    void addNFAEdge(size_t start, size_t end, const string& symbolOnEdge);
    void createTwoNFANodes();
    NFA createNFA(const string& symbolOnEdge);
    NFA mulCalc(const NFA&);
    NFA plusCalc(const NFA&);
    NFA whatCalc(const NFA&);
    NFA orCalc(const NFA&, const NFA&);
    NFA andCalc(const NFA&, const NFA&);
    stack<char> oprStack; // 运算符栈
    stack<NFA> NFAStack; // Nfa栈(数字栈)
    queue<string> suffixRe; // 后缀表达式
    // ^^^使用string而不是char存是因为转义符号的存在以及类似digit这种不是指定单个char的正则名的存在，转义符号出现时需要将转义符号\和字符一起放到后缀表达式中
    vector<NFANode> NFANodes; // 所有NFA节点
    vector<Edge> edges; // 所有的边
    NFA finalNFA; // 最后生成的NFA图

    // 生成DFA
    void generateDFA();
    void initDFATemp();
    void initDFA();
    set<size_t> findNextE(size_t index);
    map<string, map<string, string>> DFANodesTemp; // 所有的DFA节点(每个string是一个点集)
    map<size_t, map<string, size_t>> DFANodes; // 将DFANodesTemp重新索引后的结果

    // 最小化DFA
    void minimizeDFA();
    map<size_t, map<string, size_t>> minDFANodes; // 最小化DFA点集

    // 打印操作
    void printNFAMatrix();
    void printDFAMatrix() const;
    void printMinDFAMatrix() const;
};


#endif //FAMANAGER_H
